/**
 * 类组件中事件处理函数的this指向问题
 *    问题的原因：
 *        const app = new App();
          app.handleClick(); // 这样调用，handleClick 中的this是app
          const cb = app.handleClick; // 把handleClick复制给一个变量
          cb(); // handleClick 中 this 指向是 undefined

          <button onClick={this.handleClick}>{count}</button>

          button 上的 onClick 就类似与上面的 cb 。再由于 class 的函数默认开启严格模式

    解决this指向问题的方案：
      1. 提前在构造函数中做this的绑定
      2. 使用 public class fiedls 语法，结合箭头函数，直接定义事件处理函数
      3. 在 JSX 的地方，做 bind
      4. 在 JSX 的地方，提供一个 箭头函数作为事件处理函数，然后在箭头函数体内将 之前的函数当前普通函数来调用

    事件处理函数与普通函数有什么区别：
      1. 会不会接受到一个事件对象的区别：
          事件处理函数，默认会收到一个事件对象Event (React 中的事件对象Event是一个经过处理的事件对象，叫合成事件对象)
      2. 普通函数，this指向调用者。事件处理函数this默认指向 undefined

    事件处理函数传递参数该如何玩：
      1. 使用 bind 来传递参数
      2. 使用 箭头函数来传递参数 
      3. 普通函数调用返回值为一个函数，将返回的函数作为事件处理函数
 */

import { Component } from "react";

class App extends Component {
  state = {
    count: 1,
  };

  handleAdd(num, e) {
    console.log("handleAdd 最后一个参数是 事件对象", e);
    this.setState({
      count: this.state.count + num,
    });
  }

  handleGaoAdd(num) {
    return (e) => {
      this.setState({
        count: this.state.count + num,
      });
    };
  }

  render() {
    const { count } = this.state;

    return (
      <div>
        <h1>App - {count}</h1>
        {/* next-line 代码是有问题的，函数上直接加括号是不行的 */}
        {/* <button onClick={this.handleAdd(1)}>{count} + 1</button> */}

        {/* 1. 使用 bind 来传递参数 */}
        {/* 
        <button onClick={this.handleAdd.bind(this, 1)}>+ 1</button>
        <button onClick={this.handleAdd.bind(this, 2)}>+ 2</button> 
        */}

        {/* 2. 使用 箭头函数来传递参数 */}
        {/* 
        <button onClick={(e) => this.handleAdd(1, e)}>+ 1</button>
        <button onClick={(e) => this.handleAdd(2, e)}>+ 2</button>
        */}

        {/* 3. 普通函数调用返回值为一个函数，将返回的函数作为事件处理函数 */}
        <button onClick={this.handleGaoAdd(1)}>+ 1</button>
        <button onClick={this.handleGaoAdd(2)}>+ 2</button>
      </div>
    );
  }
}

// 事件处理函数与普通函数的区别
// class App extends Component {
//   state = {
//     count: 1,
//   };

//   handleClick(e) {
//     console.log("handleClick", e);
//   }

//   render() {
//     const { count } = this.state;

//     return (
//       <div>
//         <h1>App</h1>
//         <button onClick={this.handleClick}>{count}</button>
//         <button
//           onClick={(e) => {
//             this.handleClick(e);
//           }}
//         >
//           {count}
//         </button>
//       </div>
//     );
//   }
// }

// 4. 在 JSX 的地方，提供一个 箭头函数作为事件处理函数，然后在箭头函数体内将 之前的函数当前普通函数来调用
// class App extends Component {
//   state = {
//     count: 1,
//   };

//   // 原型上的
//   handleClick() {
//     console.log(111, this.state.count);
//   }

//   render() {
//     const { count } = this.state;

//     return (
//       <div>
//         <h1>App</h1>
//         <button
//           onClick={() => {
//             this.handleClick();
//           }}
//         >
//           {count}
//         </button>
//       </div>
//     );
//   }
// }

// 3. 在 JSX 的地方，做 bind
// class App extends Component {
//   state = {
//     count: 1,
//   };

//   // 原型上的
//   handleClick() {
//     console.log(111, this.state.count);
//   }

//   render() {
//     const { count } = this.state;

//     return (
//       <div>
//         <h1>App</h1>
//         <button onClick={this.handleClick.bind(this)}>{count}</button>
//       </div>
//     );
//   }
// }

// 2. 使用 public class fiedls 语法，结合箭头函数，直接定义事件处理函数
// class App extends Component {
//   state = {
//     count: 1,
//   };

//   // 原型上的
//   handleClick = () => {
//     console.log(111, this.state.count);
//   };

//   render() {
//     const { count } = this.state;

//     return (
//       <div>
//         <h1>App</h1>
//         <button onClick={this.handleClick}>{count}</button>
//       </div>
//     );
//   }
// }

// 1. 提前在构造函数中做this的绑定
// class App extends Component {
//   constructor() {
//     super();
//     // 初始化 state
//     this.state = {
//       count: 1,
//     };
//     // 绑定this，返回值直接在实例上添加了一个同名的 handleClick
//     this.handleClick = this.handleClick.bind(this);

//     // 观察实例对象
//     console.log("构造函数中 this", this);
//   }

//   // 原型上的
//   handleClick() {
//     console.log(111, this.state.count);
//   }

//   render() {
//     const { count } = this.state;

//     return (
//       <div>
//         <h1>App</h1>
//         <button onClick={this.handleClick}>{count}</button>
//       </div>
//     );
//   }
// }

export default App;
